/*
Minims .Net Playstation 3 UPNP ContentDirectory
Copyright (C) 2008  Guillaume Plourde

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2
of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Xml;
using System.IO;

using System.ComponentModel;
using System.Data;

namespace minims_lib
{
	public class MediaType
	{
		public short type; // 0 video, 1 audio, 2 image
		public string name;
		public string mine;
		public Hashtable dnla_keys;
		public bool encode;
	}
	public class ConfigManager : Service
	{
		// Public
		public MinimsConfig User;

		// Private
		FileInfo Encoder;

		// Upnp Device
		string FriendlyName = "Minims: Minimal Media Server";
		string ManufacturerURL = "http://code.google.com/p/minims/";
		string SerialNumber = "0000000001";
		string UniqueDeviceName = "41ed3443-6d88-4cdf-be4e-1b35d5dc9fb5";

		// httpd default configuration
		string Hostname = Dns.GetHostName();
		IPHostEntry Ip = Dns.GetHostByName(Dns.GetHostName());

		public ConfigManager(string path) : base("ConfigManager")
		{
			User = new MinimsConfig();
			User.Load(path);
		}

		#region Private Methodes
		#endregion
		#region Public Methodes
		/// <summary>
		/// Get hostname of this computer.
		/// </summary>
		public string GetHostname { get { return Hostname; }}
		/// <summary>
		/// Get ip of this computer.
		/// </summary>
		public string GetHostIp { get { return Ip.AddressList[0].ToString(); }}
		/// <summary>
		/// Get upnp friendly name for the device.
		/// </summary>
		public string GetFriendlyName { get { return (FriendlyName + " (" + Hostname + ")"); }}

		/// <summary>
		/// Get device serial Number
		/// </summary>
		public string GetSerialNumber { get { return SerialNumber; }}
		
		/// <summary>
		/// Get device serial Number
		/// </summary>
		public string GetUniqueDeviceName { get { return UniqueDeviceName; }}

		/// <summary>
		/// 
		/// </summary>
		public string GetManufacturerURL { get { return ManufacturerURL; }}
		#endregion
	}

	[DefaultPropertyAttribute("General")]
	public class MinimsConfig
	{
		private int _port;
		private string _deny;
		private string _allow;
		private string _path;
		private bool _transcoding;
		private string _encoder;
		private bool _video;
		private bool _audio;
		private bool _image;
		private bool _xboxcompat;

		static public List<MediaType> _mediaTypes;

		public bool Save(string path)
		{
			FileInfo fi = new FileInfo(path + "config.xml");

			if (fi.Exists && fi.IsReadOnly)
			{
				Console.WriteLine("Unable to write config.xml");
				return false;
			}

			StreamWriter config = File.CreateText(fi.FullName);
			config.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
			config.WriteLine("<minims>");
			config.WriteLine("\t<key name=\"Http_Port\">{0}</key>", _port);
			config.WriteLine("\t<key name=\"Http_Allow\">{0}</key>", _allow);
			config.WriteLine("\t<key name=\"Http_Deny\">{0}</key>", _deny);
			config.WriteLine("\t<key name=\"Http_Path\">{0}</key>", _path);
			config.WriteLine("\t<key name=\"ContentDirectory_Subfolders\">true</key>");
			config.WriteLine("\t<key name=\"Transcoder_Enable\">{0}</key>", _transcoding);
			config.WriteLine("\t<key name=\"Transcoder_Encoder\">{0}</key>", _encoder);

			config.WriteLine("\t<key name=\"Video\">{0}</key>", _video);
			config.WriteLine("\t<key name=\"Audio\">{0}</key>", _audio);
			config.WriteLine("\t<key name=\"Image\">{0}</key>", _image);
			config.WriteLine("\t<key name=\"XboxCompat\">{0}</key>", _xboxcompat);

			config.WriteLine("</minims>");
			config.Close();

			return true;
		}
		public bool Load(string path)
		{
			FileInfo fi = new FileInfo(path + "config.xml");

			if (fi.Exists)
			{
				XmlNodeList nodes;
				XmlDocument doc = new XmlDocument();
				doc.Load(fi.FullName);

				// read http settings
				nodes = doc.SelectNodes("/minims/key");

				foreach (XmlNode node in nodes)
				{
					switch (node.Attributes["name"].Value)
					{
						case "Http_Port":
							this.Port = int.Parse(node.InnerText);
							break;
						case "Http_Allow":
							this.Allow = node.InnerText;
							break;
						case "Http_Deny":
							this.Deny = node.InnerText;
							break;
						case "Http_Path":
							this.Path = node.InnerText;
							break;
						case "Transcoder_Enable":
							this.Enable = bool.Parse(node.InnerText);
							break;
						case "Transcoder_Encoder":
							this.Encoder = node.InnerText;
							break;
						case "Video":
							this._video = bool.Parse(node.InnerText);
							break;
						case "Audio":
							this._audio = bool.Parse(node.InnerText);
							break;
						case "Image":
							this._image = bool.Parse(node.InnerText);
							break;
						case "XboxCompat":
							this._xboxcompat = bool.Parse(node.InnerText);
							break;
					}
				}
				return true;
			}
			return false;
		}

		private void ParseMediaTypesNode(XmlNodeList nodes, short type)
		{
			foreach (XmlNode node in nodes)
			{
				MediaType m = new MediaType();
				m.name = node.Attributes["name"].Value;
				m.mine = node.Attributes["mime"].Value;
				m.dnla_keys = new Hashtable();

				XmlNode dnlaNode = node.SelectSingleNode("/types/video/dnla");
				XmlNodeList dnlaKeys = dnlaNode.SelectNodes("descendant::key");

				foreach (XmlNode key in dnlaKeys)
				{
					m.dnla_keys.Add(key.Attributes["name"].Value, key.InnerText);
				}

				XmlNode encodingNode = node.SelectSingleNode("/types/video/encoding");
				XmlNodeList encodingKeys = encodingNode.SelectNodes("descendant::key");

				foreach (XmlNode key in encodingKeys)
				{
					//m.dnla_keys.Add(key.Attributes["name"].Value, key.InnerText);
				}
				
				m.type = type;
				_mediaTypes.Add(m);
			}
		}
		public bool LoadMimeTypes(string path)
		{
			FileInfo fi = new FileInfo(path + "mime-types.xml");
			_mediaTypes = new List<MediaType>();
			if (fi.Exists)
			{
				XmlNodeList nodes;
				XmlDocument doc = new XmlDocument();
				doc.Load(fi.FullName);

				ParseMediaTypesNode(doc.SelectNodes("/types/video"), 0);
				ParseMediaTypesNode(doc.SelectNodes("/types/audio"), 1);
				ParseMediaTypesNode(doc.SelectNodes("/types/image"), 2);

				return true;
			}
			return false;
		}

		// Http Service
		[CategoryAttribute("Http Service"), DescriptionAttribute("Port")]
		public int Port
		{
			get	{ return _port;	}
			set	{ _port = value; }
		}
		[CategoryAttribute("Http Service"), DescriptionAttribute("Deny")]
		public string Deny
		{
			get { return _deny; }
			set { _deny = value; }
		}
		[CategoryAttribute("Http Service"), DescriptionAttribute("Allow")]
		public string Allow
		{
			get { return _allow; }
			set { _allow = value; }
		}
		[CategoryAttribute("Http Service"), DescriptionAttribute("Path")]
		public string Path
		{
			get { return _path; }
			set { _path = value; }
		}
		// Trasncoder
		[CategoryAttribute("Transcoding"), DescriptionAttribute("Enable")]
		public bool Enable
		{
			get { return _transcoding; }
			set { _transcoding = value; }
		}
		[CategoryAttribute("Transcoding"), DescriptionAttribute("Encoder")]
		public string Encoder
		{
			get { return _encoder; }
			set { _encoder = value; }
		}

		[CategoryAttribute("Media"), DescriptionAttribute("Video")]
		public bool Video
		{
			get { return _video; }
			set { _video = value; }
		}
		[CategoryAttribute("Media"), DescriptionAttribute("Audio")]
		public bool Audio
		{
			get { return _audio; }
			set { _audio = value; }
		}
		[CategoryAttribute("Media"), DescriptionAttribute("Image")]
		public bool Image
		{
			get { return _image; }
			set { _image = value; }
		}
		[CategoryAttribute("Media"), DescriptionAttribute("Xbox 360 Compatibility")]
		public bool XboxCompat
		{
			get { return _xboxcompat; }
			set { _xboxcompat = value; }
		}
		public int GetMediaTypeCount()
		{
			return _mediaTypes.Count;
		}
		public MediaType GetMediaType(int index)
		{
			return _mediaTypes[index];
		}
	}
}
